package com.zhz.company.config.shiro;

import com.zhz.common.properties.RedisProperties;
import com.zhz.common.shiro.realm.IhrmRealm;
import com.zhz.common.shiro.session.CustomSessionManager;
import com.zhz.common.utils.StrPoolUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * shiro配置
 *
 * @author zhouhengzhe
 * @date 2023/5/28
 */
@Configuration
public class ShiroConfiguration {

    private final RedisProperties redisProperties;

    private final SsoProperties ssoProperties;

    @Autowired
    public ShiroConfiguration(RedisProperties redisProperties,
                              SsoProperties ssoProperties) {
        this.redisProperties = redisProperties;
        this.ssoProperties = ssoProperties;
    }

    /**
     * 创建realm
     *
     * @return 返回realm
     */
    @Bean
    public IhrmRealm ihrmRealm() {
        return new IhrmRealm();
    }

    /**
     * 2.创建安全管理器
     *
     * @param realm realm
     * @return
     */
    @Bean
    public SecurityManager getSecurityManager(IhrmRealm realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        //将自定义的会话管理器注册到安全管理器中
        securityManager.setSessionManager(sessionManager());
        //将自定义的redis缓存管理器注册到安全管理器中
        securityManager.setCacheManager(cacheManager());
        return securityManager;
    }


    //3.配置shiro的过滤器工厂

    /**
     * 再web程序中，shiro进行权限控制全部是通过一组过滤器集合进行控制
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        //1.创建过滤器工厂
        ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
        //2.设置安全管理器
        filterFactory.setSecurityManager(securityManager);
        //3.通用配置（跳转登录页面，未授权跳转的页面）
        //跳转url地址
        filterFactory.setLoginUrl(ssoProperties.getLoginUrl());
        //未授权的url
        filterFactory.setUnauthorizedUrl(ssoProperties.getUnauthorizedUrl());
        //4.设置过滤器集合
        Map<String, String> filterMap = new LinkedHashMap<>();
        List<String> noAuthUrls = ssoProperties.getNoAuthUrls();
        if (CollectionUtils.isNotEmpty(noAuthUrls)) {
            noAuthUrls.forEach(noAuthUrl -> {
                //anon -- 匿名访问
                filterMap.put(noAuthUrl, StrPoolUtils.ANON);
            });
        }
        //authc -- 认证之后访问（登录）
        filterMap.put(StrPoolUtils.ALL, StrPoolUtils.AUTHC);
        //perms -- 具有某中权限 (使用注解配置授权)
        filterFactory.setFilterChainDefinitionMap(filterMap);
        return filterFactory;
    }

    /**
     * 1.redis的控制器，操作redis
     */
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(redisProperties.getHost());
        redisManager.setPort(redisProperties.getPort());
        redisManager.setPassword(redisProperties.getPassword());
        return redisManager;
    }

    /**
     * 2.sessionDao
     */
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO sessionDAO = new RedisSessionDAO();
        sessionDAO.setRedisManager(redisManager());
        return sessionDAO;
    }

    /**
     * 3.会话管理器
     */
    public DefaultWebSessionManager sessionManager() {
        CustomSessionManager sessionManager = new CustomSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
        //禁用cookie
        sessionManager.setSessionIdCookieEnabled(false);
        //禁用url重写   url;jsessionid=id
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }

    /**
     * 4.缓存管理器
     */
    public RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }


    /**
     * 开启对shior注解的支持
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

}
